package com.jtw.conf.shiro;

import lombok.extern.slf4j.Slf4j;
import org.apache.shiro.cache.ehcache.EhCacheManager;
import org.apache.shiro.codec.Base64;
import org.apache.shiro.spring.LifecycleBeanPostProcessor;
import org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor;
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.web.mgt.CookieRememberMeManager;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.apache.shiro.web.servlet.SimpleCookie;
import org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import javax.servlet.Filter;
import java.util.Map;

/**
 * DESCRIPT:shiro配置类
 *
 *
 * @author cjsky666
 * @date 2018-8-30 18:03
 */
@Configuration
@Slf4j
public class CustomShiroConf {

    public static final String PUBLIC_REQUEST_URL_PERMISSION  = "anon";
    public static final String PRIVATE_REQUEST_URL_PERMISSION  = "authc";
    /**
     * 缓存管理
     *
     * @return
     */
    @Bean
    public EhCacheManager getEhCacheManager() {
        EhCacheManager cacheManager = new EhCacheManager();
        cacheManager.setCacheManagerConfigFile("classpath:config/ehcache-shiro.xml");
        return cacheManager;
    }
    /**
     * 注入自定义登录校验，并添加密码匹配检验器
     * @return
     */
    @Bean
    public CustomAuthorizingRealm customshiroRealm(RetryLimitHashedCredentialsMatcher matcher){
        CustomAuthorizingRealm customshiroRealm = new CustomAuthorizingRealm();
        customshiroRealm.setCacheManager(getEhCacheManager());
        customshiroRealm.setCredentialsMatcher(matcher);
        return  customshiroRealm;
    }

    /**
     * 凭证匹配器
     *
     * @param cacheManager
     * @return
     */
    @Bean
    public RetryLimitHashedCredentialsMatcher getRetryLimitHashedCredentialsMatcher(EhCacheManager cacheManager) {
        RetryLimitHashedCredentialsMatcher matcher = new RetryLimitHashedCredentialsMatcher(cacheManager);
        matcher.setHashAlgorithmName("md5");
        matcher.setHashIterations(2);
        return matcher;
    }

    /**
     * cookie基本配置 过期时间 一星期
     * @return
     */
    @Bean
    public SimpleCookie getrememberMeCookie(){
        SimpleCookie simpleCookie = new SimpleCookie("rememberMe");
        //如果httyOnly设置为true，则客户端不会暴露给客户端脚本代码，使用HttpOnly cookie有助于减少某些类型的跨站点脚本攻击；
        simpleCookie.setHttpOnly(true);
        simpleCookie.setPath("/");
        simpleCookie.setDomain("localhost");
        //记住我cookie生效时间,默认30天 ,单位秒：60 * 60 * 24 * 30
        simpleCookie.setMaxAge(604800);
        return simpleCookie;
    }

    @Bean
    public CookieRememberMeManager getcookieRememberMeManager(){
        CookieRememberMeManager cookieRememberMeManager = new CookieRememberMeManager();
        byte [] cipherKey = Base64.decode("5VUuR2rgQ8EZpepxkKhYpg==");
        cookieRememberMeManager.setCipherKey(cipherKey);
        cookieRememberMeManager.setCookie(getrememberMeCookie());
        return cookieRememberMeManager;
    }
    /**
     * 安全管理器，配置上自定义的realm
     * @return
     */
    @Bean(name = "securityManager")
    public DefaultWebSecurityManager defaultWebSecurityManager(CustomAuthorizingRealm customAuthorizingRealm){
        DefaultWebSecurityManager defaultSecurityManager = new DefaultWebSecurityManager();
        defaultSecurityManager.setRealm(customAuthorizingRealm);
        defaultSecurityManager.setRememberMeManager(getcookieRememberMeManager());
        return defaultSecurityManager;
    }
    /**
     * LifecycleBeanPostProcessor，
     * 实现类统一在其内部自动分别调用了Initializable.init()和Destroyable.destroy()方法，
     * 达到管理shiro bean生命周期的目的。避免开发时热部署导致的bean实体未销毁问题
     */
//            (name = "lifecycleBeanPostProcessor")
    @Bean
    public LifecycleBeanPostProcessor lifecycleBeanPostProcessor() {
        return new LifecycleBeanPostProcessor();
    }
    /**
     * 支持Shiro对Controller的方法级AOP安全控制
     */
    @Bean
    public DefaultAdvisorAutoProxyCreator getDefaultAdvisorAutoProxyCreator() {
        DefaultAdvisorAutoProxyCreator creator = new DefaultAdvisorAutoProxyCreator();
        creator.setProxyTargetClass(true);
        return creator;
    }
    /**
     * 开启shiro aop注解支持.
     * 使用代理方式;所以需要开启代码支持;
     */
    @Bean
    public AuthorizationAttributeSourceAdvisor getAuthorizationAttributeSourceAdvisor(DefaultWebSecurityManager securityManager) {
        AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor = new AuthorizationAttributeSourceAdvisor();
        authorizationAttributeSourceAdvisor.setSecurityManager(securityManager);
        return authorizationAttributeSourceAdvisor;
    }

    @Bean
    public ShiroFilterFactoryBean shiroFilterFactoryBean(DefaultWebSecurityManager defaultWebSecurityManager){
        log.info("shirobean初始化3");
        ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
        Map<String,Filter> filters =  shiroFilterFactoryBean.getFilters();
        log.info(filters.toString());
        log.info(filters.size()+"");
        filters.put(CustomAuthorizationFilter.FilterKey, new CustomAuthorizationFilter());
        // 必须设置 SecurityManager
        shiroFilterFactoryBean.setSecurityManager(defaultWebSecurityManager);
        // 如果不设置默认会自动寻找Web工程根目录下的"/login.jsp"页面
        shiroFilterFactoryBean.setLoginUrl("/sys/user/unLogin");
        return shiroFilterFactoryBean;
    }
}
